#include <QVariantMap>
#include "biblereaderverseheaderparser.h"
#include "Logger.h"

typedef struct _book {
    QString name;
    int id;
} Book;

QVector<BibleVersePos> BibleReaderVerseHeaderParser::parse(QString header)
{
    QString bookName, chapter, verse1, verse2;

    // map for book
    QVariantMap bookMap;
    QVector<Book> books = {
        {"创", 1}, {"创世记", 1},
        {"出", 2}, {"出埃及记", 2},
        {"利", 3}, {"利未记", 3},
        {"民", 4}, {"民数记", 4},
        {"申", 5}, {"申命记", 5},
        {"书", 6}, {"约书亚记", 6},
        { "士", 7},{"士师记", 7},
        { "得", 8},{"路得记", 8},
        { "撒上", 9},{"撒母耳记上", 9},
        { "撒下", 10},{"撒母耳记下", 10},
        { "王上", 11},{"列王纪上", 11},
        { "王下", 12},{"列王纪下", 12},
        { "代上", 13},{"历代志上", 13},
        { "代下", 14},{"历代志下", 14},
        { "拉", 15},{"以斯拉记", 15},
        { "尼", 16},{"尼希米记", 16},
        { "斯", 17},{"以斯帖记", 17},
        { "伯", 18},{"约伯记", 18},
        { "诗", 19},{"诗篇", 19},
        { "箴", 20},{"箴言", 20},{"箴言书", 20},
        { "传", 21},{"传道书", 21},
        { "歌", 22},{"雅歌", 22},
        { "赛", 23},{"以赛亚书", 23},
        { "耶", 24},{"耶利米书", 24},
        { "哀", 25},{"耶利米哀歌", 25},
        { "结", 26},{"以西结书", 26},
        { "但", 27},{"但以理书", 27},
        { "何", 28},{"何西阿书", 28},
        { "珥", 29},{"约珥书", 29},
        { "摩", 30},{"阿摩司书", 30},
        { "俄", 31},{"俄巴底亚书", 31},
        { "拿", 32},{"约拿书", 32},
        { "弥", 33},{"弥迦书", 33},
        { "鸿", 34},{"那鸿书", 34},
        { "哈", 35},{"哈巴谷书", 35},
        { "番", 36},{"西番雅书", 36},
        { "该", 37},{"哈该书", 37},
        { "亚", 38}, {"撒迦利亚书", 38},
        { "玛", 39},{"玛拉基书", 39},
        { "太", 40},{"马太福音", 40},
        { "可", 41},{"马可福音", 41},
        { "路", 42},{"路加福音", 42},
        { "约", 43},{"约翰福音", 43},
        { "徒", 44},{"使徒行传", 44},
        { "罗", 45},{"罗马书", 45},
        { "林前", 46},{"哥林多前书", 46},
        { "林后", 47},{"哥林多后书", 47},
        { "加", 48},{"加拉太书", 48},
        { "弗", 49},{"以弗所书", 49},
        { "腓", 50},{"腓立比书", 50},
        { "西", 51},{"歌罗西书", 51},
        { "帖前", 52},{"帖撒罗尼迦前书", 52},
        { "帖后", 53},{"帖撒罗尼迦后书", 53},
        { "提前", 54},{"提摩太前书", 54},
        { "提后", 55},{"提摩太后书", 55},
        { "多", 56},{"提多书", 56},
        { "门", 57},{"腓利门书", 57},
        { "来", 58},{"希伯来书", 58},
        { "雅", 59},{"雅各书", 59},
        { "彼前", 60},{"彼得前书", 60},
        { "彼后", 61},{"彼得后书", 61},
        { "约一", 62},{"约翰一书", 62},{ "约壹", 62},{"约翰壹书", 62},
        { "约二", 63},{ "约贰", 63},{"约翰二书", 63},{"约翰贰书", 63},
        { "约三", 64},{"约翰三书", 64},{ "约叁", 64},{"约翰叁书", 64},
        { "犹", 65},{"犹大书", 65},
        { "启", 66},{"启示录", 66},
            };

    for (int i = 0; i < books.size(); i++) {
        bookMap.insert(books[i].name, books[i].id);
    }


    // chapter : chinese to number
    QVariantMap chapterMap;
    chapterMap.insert("一", 1);
    chapterMap.insert("二", 2);
    chapterMap.insert("三", 3);
    chapterMap.insert("四", 4);
    chapterMap.insert("五", 5);
    chapterMap.insert("六", 6);
    chapterMap.insert("七", 7);
    chapterMap.insert("八", 8);
    chapterMap.insert("九", 9);
    chapterMap.insert("十", 10);
    chapterMap.insert("十一", 11);
    chapterMap.insert("一一", 11);
    chapterMap.insert("十二", 12);
    chapterMap.insert("一二", 12);
    chapterMap.insert("十三", 13);
    chapterMap.insert("一三", 13);
    chapterMap.insert("十四", 14);
    chapterMap.insert("一四", 14);
    chapterMap.insert("十五", 15);
    chapterMap.insert("一五", 15);
    chapterMap.insert("十六", 16);
    chapterMap.insert("一六", 16);
    chapterMap.insert("十七", 17);
    chapterMap.insert("一七", 17);
    chapterMap.insert("十八", 18);
    chapterMap.insert("一八", 18);
    chapterMap.insert("十九", 19);
    chapterMap.insert("一九", 19);
    chapterMap.insert("二十", 20);
    chapterMap.insert("二○", 20);
    chapterMap.insert("廿十", 20);
    chapterMap.insert("二一", 21);
    chapterMap.insert("廿一", 21);
    chapterMap.insert("二十一", 21);
    chapterMap.insert("二二", 22);
    chapterMap.insert("廿二", 22);
    chapterMap.insert("二十二", 22);
    chapterMap.insert("二三", 23);
    chapterMap.insert("廿三", 23);
    chapterMap.insert("二十三", 23);
    chapterMap.insert("二四", 24);
    chapterMap.insert("廿四", 24);
    chapterMap.insert("二十四", 24);
    chapterMap.insert("二五", 25);
    chapterMap.insert("廿五", 25);
    chapterMap.insert("二十五", 25);
    chapterMap.insert("二六", 26);
    chapterMap.insert("廿六", 26);
    chapterMap.insert("二十六", 26);
    chapterMap.insert("二七", 27);
    chapterMap.insert("廿七", 27);
    chapterMap.insert("二十七", 27);
    chapterMap.insert("二八", 28);
    chapterMap.insert("廿八", 28);
    chapterMap.insert("二十八", 28);
    chapterMap.insert("二九", 29);
    chapterMap.insert("廿九", 29);
    chapterMap.insert("二十九", 29);
    chapterMap.insert("三十", 30);
    chapterMap.insert("三一", 31);
    chapterMap.insert("三十一", 31);
    chapterMap.insert("三二", 32);
    chapterMap.insert("三十二", 32);
    chapterMap.insert("三三", 33);
    chapterMap.insert("三十三", 33);
    chapterMap.insert("三四", 34);
    chapterMap.insert("三十四", 34);
    chapterMap.insert("三五", 35);
    chapterMap.insert("三十五", 35);
    chapterMap.insert("三六", 36);
    chapterMap.insert("三十六", 36);
    chapterMap.insert("三七", 37);
    chapterMap.insert("三十七", 37);
    chapterMap.insert("三八", 38);
    chapterMap.insert("三十八", 38);
    chapterMap.insert("三九", 39);
    chapterMap.insert("三十九", 39);
    chapterMap.insert("四十", 40);
    chapterMap.insert("四一", 41);
    chapterMap.insert("四十一", 41);
    chapterMap.insert("四二", 42);
    chapterMap.insert("四十二", 42);
    chapterMap.insert("四三", 43);
    chapterMap.insert("四十三", 43);
    chapterMap.insert("四四", 44);
    chapterMap.insert("四十四", 44);
    chapterMap.insert("四五", 45);
    chapterMap.insert("四十五", 45);
    chapterMap.insert("四六", 46);
    chapterMap.insert("四十六", 46);
    chapterMap.insert("四七", 47);
    chapterMap.insert("四十七", 47);
    chapterMap.insert("四八", 48);
    chapterMap.insert("四十八", 48);
    chapterMap.insert("四九", 49);
    chapterMap.insert("四十九", 49);
    chapterMap.insert("五十", 50);
    chapterMap.insert("五十一", 51);
    chapterMap.insert("五十二", 52);
    chapterMap.insert("五十三", 53);
    chapterMap.insert("五十四", 54);
    chapterMap.insert("五十五", 55);
    chapterMap.insert("五十六", 56);
    chapterMap.insert("五十七", 57);
    chapterMap.insert("五十八", 58);
    chapterMap.insert("五十九", 59);
    chapterMap.insert("六十", 60);
    chapterMap.insert("六十一", 61);
    chapterMap.insert("六十二", 62);
    chapterMap.insert("六十三", 63);
    chapterMap.insert("六十四", 64);
    chapterMap.insert("六十五", 65);
    chapterMap.insert("六十六", 66);
    chapterMap.insert("六十七", 67);
    chapterMap.insert("六十八", 68);
    chapterMap.insert("六十九", 69);
    chapterMap.insert("七十", 70);
    chapterMap.insert("七十一", 71);
    chapterMap.insert("七十二", 72);
    chapterMap.insert("七十三", 73);
    chapterMap.insert("七十四", 74);
    chapterMap.insert("七十五", 75);
    chapterMap.insert("七十六", 76);
    chapterMap.insert("七十七", 77);
    chapterMap.insert("七十八", 78);
    chapterMap.insert("七十九", 79);
    chapterMap.insert("八十", 80);
    chapterMap.insert("八十一", 81);
    chapterMap.insert("八十二", 82);
    chapterMap.insert("八十三", 83);
    chapterMap.insert("八十四", 84);
    chapterMap.insert("八十五", 85);
    chapterMap.insert("八十六", 86);
    chapterMap.insert("八十七", 87);
    chapterMap.insert("八十八", 88);
    chapterMap.insert("八十九", 89);
    chapterMap.insert("九十", 90);
    chapterMap.insert("九十一", 91);
    chapterMap.insert("九十二", 92);
    chapterMap.insert("九十三", 93);
    chapterMap.insert("九十四", 94);
    chapterMap.insert("九十五", 95);
    chapterMap.insert("九十六", 96);
    chapterMap.insert("九十七", 97);
    chapterMap.insert("九十八", 98);
    chapterMap.insert("九十九", 99);
    chapterMap.insert("一○○", 100);
    chapterMap.insert("一○一", 101);
    chapterMap.insert("一○二", 102);
    chapterMap.insert("一○三", 103);
    chapterMap.insert("一○四", 104);
    chapterMap.insert("一○五", 105);
    chapterMap.insert("一○六", 106);
    chapterMap.insert("一○七", 107);
    chapterMap.insert("一○八", 108);
    chapterMap.insert("一○九", 109);
    chapterMap.insert("一一○", 110);
    chapterMap.insert("一一一", 111);
    chapterMap.insert("一一二", 112);
    chapterMap.insert("一一三", 113);
    chapterMap.insert("一一四", 114);
    chapterMap.insert("一一五", 115);
    chapterMap.insert("一一六", 116);
    chapterMap.insert("一一七", 117);
    chapterMap.insert("一一八", 118);
    chapterMap.insert("一一九", 119);
    chapterMap.insert("一二○", 120);
    chapterMap.insert("一二一", 121);
    chapterMap.insert("一二二", 122);
    chapterMap.insert("一二三", 123);
    chapterMap.insert("一二四", 124);
    chapterMap.insert("一二五", 125);
    chapterMap.insert("一二六", 126);
    chapterMap.insert("一二七", 127);
    chapterMap.insert("一二八", 128);
    chapterMap.insert("一二九", 129);
    chapterMap.insert("一三○", 130);
    chapterMap.insert("一三一", 131);
    chapterMap.insert("一三二", 132);
    chapterMap.insert("一三三", 133);
    chapterMap.insert("一三四", 134);
    chapterMap.insert("一三五", 135);
    chapterMap.insert("一三六", 136);
    chapterMap.insert("一三七", 137);
    chapterMap.insert("一三八", 138);
    chapterMap.insert("一三九", 139);
    chapterMap.insert("一四○", 140);
    chapterMap.insert("一四一", 141);
    chapterMap.insert("一四二", 142);
    chapterMap.insert("一四三", 143);
    chapterMap.insert("一四四", 144);
    chapterMap.insert("一四五", 145);
    chapterMap.insert("一四六", 146);
    chapterMap.insert("一四七", 147);
    chapterMap.insert("一四八", 148);
    chapterMap.insert("一四九", 149);
    chapterMap.insert("一五○", 150);

    QString patternBookNames = QString("(创|创世记|创世纪|出|出埃及记|利|利未记|民|民数记|申|申命记|") +
            QString("书|约书亚记|士|士师记|得|路得记|撒上|撒母耳记上|撒下|撒母耳记下|王上|列王纪上|列王记上|王下|列王纪下|列王记下|代上|历代志上|代下|历代志下|拉|以斯拉记|尼|尼希米记|斯|以斯帖记|") +
            QString("伯|约伯记|诗|诗篇|箴|箴言书|传|传道书|歌|雅歌|雅歌书|") +
            QString("赛|以赛亚书|耶|耶利米书|哀|耶利米哀歌|结|以西结书|但|但以理书|何|何西阿书|珥|约珥书|摩|阿摩司书|俄|俄巴底亚书|拿|约拿书|弥|弥迦书|鸿|那鸿书|哈|哈巴谷书|番|西番雅书|该|哈该书|亚|撒迦利亚书|玛|玛拉基书|") +
            QString("太|马太福音|可|马可福音|路|路加福音|约|约翰福音|") +
            QString("徒|使徒行传|") +
            QString("罗|罗马书|林前|哥林多前书|林后|哥林多后书|加|加拉太书|弗|以弗所书|腓|腓立比书|西|歌罗西书|帖前|帖撒罗尼迦前书|帖后|帖撒罗尼迦后书|提前|提摩太前书|提后|提摩太后书|多|提多书|门|腓利门书|来|希伯来书|") +
            QString("雅|雅各书|彼前|彼得前书|彼后|彼得后书|约一|约壹|约翰壹书|约翰一书|约二|约贰|约翰贰书|约翰二书|约三|约叁|约翰叁书|约翰三书|犹|犹大书|启|启示录)");

    QString patternChineseChapters = "";
    patternChineseChapters.append("(一|二|三|四|五|六|七|八|九|十|");
    patternChineseChapters.append("十一|一一|十二|一二|十三|一三|十四|一四|十五|一五|十六|一六|十七|一七|十八|一八|十九|一九|二十|二○|");
    patternChineseChapters.append("二一|廿一|二十一|二二|廿二|二十二|二三|廿三|二十三|二四|廿四|二十四|二五|廿五|二十五|二六|廿六|二十六|二七|廿七|二十七|二八|廿八|二十八|二九|廿九|二十九|三十|");
    patternChineseChapters.append("三一|三十一|三二|三十二|三三|三十三|三四|三十四|三五|三十五|三六|三十六|三七|三十七|三八|三十八|三九|三十九|四十|");
    patternChineseChapters.append("四一|四十一|四二|四十二|四三|四十三|四四|四十四|四五|四十五|四六|四十六|四七|四十七|四八|四十八|四九|四十九|五十|");
    patternChineseChapters.append("五一|五十一|五二|五十二|五三|五十三|五四|五十四|五五|五十五|五六|五十六|五七|五十七|五八|五十八|五九|五十九|六十|");
    patternChineseChapters.append("六一|六十一|六二|六十二|六三|六十三|六四|六十四|六五|六十五|六六|六十六|六七|六十七|六八|六十八|六九|六十九|七十|");
    patternChineseChapters.append("七一|七十一|七二|七十二|七三|七十三|七四|七十四|七五|七十五|七六|七十六|七七|七十七|七八|七十八|七九|七十九|八十|");
    patternChineseChapters.append("八一|八十一|八二|八十二|八三|八十三|八四|八十四|八五|八十五|八六|八十六|八七|八十七|八八|八十八|八九|八十九|九十|");
    patternChineseChapters.append("九一|九十一|九二|九十二|九三|九十三|九四|九十四|九五|九十五|九六|九十六|九七|九十七|九八|九十八|九九|九十九|一○○|");
    patternChineseChapters.append("一○一|一○二|一○三|一○四|一○五|一○六|一○七|一○八|一○九|一一○|");
    patternChineseChapters.append("一一一|一一二|一一三|一一四|一一五|一一六|一一七|一一八|一一九|一二○|");
    patternChineseChapters.append("一二一|一二二|一二三|一二四|一二五|一二六|一二七|一二八|一二九|一三○|");
    patternChineseChapters.append("一三一|一三二|一三三|一三四|一三五|一三六|一三七|一三八|一三九|一四○|");
    patternChineseChapters.append("一四一|一四二|一四三|一四四|一四五|一四六|一四七|一四八|一四九|一五○)");

    // save parsed result
    QVector<BibleVersePos> versePoses;
    QString pattern = "";
    QRegularExpression reg;
    QRegularExpressionMatch matched;

    // pattern 1: 可十一1～14 / 可十一1
    pattern.append(patternBookNames).append(patternChineseChapters).append("(\\d+)[-～~]*(\\d*)");
    reg.setPattern(pattern);
    matched = reg.match(header);

    if (matched.hasMatch()) {
        bookName = matched.captured(1);
        chapter = matched.captured(2);
        verse1 = matched.captured(3);
        verse2 = matched.captured(4);

        BibleVersePos start = BibleVersePos(bookMap.value(bookName).toInt(),
                             chapterMap.value(chapter).toInt(),
                             verse1.toInt());
        versePoses.push_back(start);
        if (!verse2.isEmpty()) {
            BibleVersePos end = BibleVersePos(bookMap.value(bookName).toInt(),
                                              chapterMap.value(chapter).toInt(),
                                              verse2.toInt());
            versePoses.push_back(end);
        }

        return versePoses;
    }

    // pattern 2: 可11:1-14 / 可11:1
    pattern = patternBookNames + QString("(\\d+):(\\d+)[-~～]*(\\d*)");
    reg.setPattern(pattern);
    matched = reg.match(header);

    if (matched.hasMatch()) {
        LOG_INFO() << matched.capturedTexts();
        bookName = matched.captured(1);
        chapter = matched.captured(2);
        verse1 = matched.captured(3);
        verse2 = matched.captured(4);

        BibleVersePos start = BibleVersePos(bookMap.value(bookName).toInt(),
                             chapter.toInt(),
                             verse1.toInt());
        versePoses.push_back(start);
        if (!verse2.isEmpty()) {
            BibleVersePos end = BibleVersePos(bookMap.value(bookName).toInt(),
                                              chapter.toInt(),
                                              verse2.toInt());
            versePoses.push_back(end);
        }

        return versePoses;
    }

    // pattern 3: 11:1-14 / 11:1 current book is Mark
    pattern = QString("(\\d+):(\\d+)[-~～]*(\\d*)");
    reg.setPattern(pattern);
    matched = reg.match(header);

    if (matched.hasMatch()) {
        chapter = matched.captured(1);
        verse1 = matched.captured(2);
        verse2 = matched.captured(3);

        // book id is -1, means current book
        BibleVersePos start = BibleVersePos(-1,
                             chapter.toInt(),
                             verse1.toInt());
        versePoses.push_back(start);
        if (!verse2.isEmpty()) {
            BibleVersePos end = BibleVersePos(-1,
                                              chapter.toInt(),
                                              verse2.toInt());
            versePoses.push_back(end);
        }

        return versePoses;
    }

    // pattern 4: 十一1~14 / 十一1-14 / 十一1 current book is Mark
    pattern = patternChineseChapters + QString("(\\d+)[～~-]*(\\d*)");
    reg.setPattern(pattern);
    matched = reg.match(header);

    if (matched.hasMatch()) {
        chapter = matched.captured(1);
        verse1 = matched.captured(2);
        verse2 = matched.captured(3);

        // book id is -1, means current book
        BibleVersePos start = BibleVersePos(-1,
                             chapterMap[chapter].toInt(),
                             verse1.toInt());
        versePoses.push_back(start);
        if (!verse2.isEmpty()) {
            BibleVersePos end = BibleVersePos(-1,
                                              chapterMap[chapter].toInt(),
                                              verse2.toInt());
            versePoses.push_back(end);
        }

        return versePoses;
    }

    // default, none verses parsed
    return versePoses;
}

BibleReaderVerseHeaderParser::BibleReaderVerseHeaderParser()
{

}

